﻿using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;

namespace Nes4Net.UI
{
    public partial class Form1 : Form
    {
        private Nes nes;
        private System.Threading.Timer timer;
        private System.Threading.Timer timer2;

        #region
        private WaveOut player;
        private AudioWaveProvider audioWaveProvider;
        #endregion

        public Form1()
        {
            InitializeComponent();
            this.KeyPreview = true;
            this.KeyDown += Form1_KeyDown;
            this.KeyUp += Form1_KeyUp;
            timer = new System.Threading.Timer(TriggerFrame, null, Timeout.Infinite, Timeout.Infinite);
            timer2 = new System.Threading.Timer(RefreshStatus, null, Timeout.Infinite, Timeout.Infinite);
        }

        private void HandleStatus(String msg)
        {
            Invoke(() => 
            {
                this.txtBoxTips.Text += $"{msg}{Environment.NewLine}";
            });
        }

        public void AudioCallBack()
        {
            nes.Frame();
        }

        private void HandleFrame(Int32[] buff)
        {
            var tmpArr = buff.Clone() as Int32[];
            pictureBox1.Image = Utils.Int32ToImage(tmpArr);
        }

        private void RefreshStatus(Object state)
        {
            Invoke(() =>
            {
                lblFPS.Text = $"FPS: {nes.GetFPS()}";
            });
        }

        private void TriggerFrame(Object state)
        {
            //if(audioWaveProvider.CanFrame())
            {
                nes?.Frame();
            }
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if(nes == null)
            {
                return;
            }
            if (e.KeyData == Keys.W)
            {
                nes.ButtonDown(0, Controller.BUTTON_UP);
            }
            else if (e.KeyData == Keys.A)
            {
                nes.ButtonDown(0, Controller.BUTTON_LEFT);
            }
            else if (e.KeyData == Keys.S)
            {
                nes.ButtonDown(0, Controller.BUTTON_DOWN);
            }
            else if (e.KeyData == Keys.D)
            {
                nes.ButtonDown(0, Controller.BUTTON_RIGHT);
            }
            else if (e.KeyData == Keys.G)
            {
                nes.ButtonDown(0, Controller.BUTTON_SELECT);
            }
            else if (e.KeyData == Keys.H)
            {
                nes.ButtonDown(0, Controller.BUTTON_START);
            }
            else if (e.KeyData == Keys.K)
            {
                nes.ButtonDown(0, Controller.BUTTON_A);
            }
            else if (e.KeyData == Keys.L)
            {
                nes.ButtonDown(0, Controller.BUTTON_B);
            }
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            if (nes == null)
            {
                return;
            }
            if (e.KeyData == Keys.W)
            {
                nes.ButtonUp(0, Controller.BUTTON_UP);
            }
            else if (e.KeyData == Keys.A)
            {
                nes.ButtonUp(0, Controller.BUTTON_LEFT);
            }
            else if (e.KeyData == Keys.S)
            {
                nes.ButtonUp(0, Controller.BUTTON_DOWN);
            }
            else if (e.KeyData == Keys.D)
            {
                nes.ButtonUp(0, Controller.BUTTON_RIGHT);
            }
            else if (e.KeyData == Keys.G)
            {
                nes.ButtonUp(0, Controller.BUTTON_SELECT);
            }
            else if (e.KeyData == Keys.H)
            {
                nes.ButtonUp(0, Controller.BUTTON_START);
            }
            else if (e.KeyData == Keys.K)
            {
                nes.ButtonUp(0, Controller.BUTTON_A);
            }
            else if (e.KeyData == Keys.L)
            {
                nes.ButtonUp(0, Controller.BUTTON_B);
            }
        }

        private void BtnLoadNes_Click(object sender, EventArgs e)
        {
            var result = openFileDialog1.ShowDialog(this);
            if (result == DialogResult.OK)
            {
                var nesPath = openFileDialog1.FileName;
                this.txtBoxNesPath.Text = nesPath;

                Release();

                try
                {
                    audioWaveProvider = new AudioWaveProvider
                    {
                        ReadCallBack = AudioCallBack
                    };

                    player = new WaveOut();
                    player.Init(audioWaveProvider);
                    var data = Utils.ReadFile2(nesPath);
                    nes = new Nes(new NesOpts
                    {
                        PreferredFrameRate = 30,
                        OnFrame = HandleFrame,
                        OnAudioSample = audioWaveProvider.Write,
                        EmulateSound = true,
                        OnStatusUpdate = HandleStatus
                    });
                    nes.LoadROM(data);
                    timer.Change(TimeSpan.FromSeconds(2), TimeSpan.FromMilliseconds(20));
                    timer2.Change(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
                    player.Play();
                }
                catch
                {
                    
                }
            }
        }


        private void Release()
        {
            audioWaveProvider?.Dispose();
            audioWaveProvider=null;
            player?.Dispose();
            player = null;
        }
    }
}
